package com.ultrapower.ultracsa.product.service.impl;

import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.RequestContext;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ultrapower.ultracsa.product.dao.IPDao;
import com.ultrapower.ultracsa.product.dao.ModelDao;
import com.ultrapower.ultracsa.product.pojo.IP;
import com.ultrapower.ultracsa.product.pojo.IPLog;
import com.ultrapower.ultracsa.product.pojo.Server;
import com.ultrapower.ultracsa.product.service.IPService;
import com.ultrapower.ultracsa.product.util.IpAddressUtil;
import com.ultrapower.ultracsa.product.util.uploadBase;

/**
 * 
 * 作者: GuoPengFei
 * 
 * 日期: 2016 4 22
 * 
 * 版权说明：北京神州泰岳软件股份有限公司
 * 
 * TODO ip配置服务端
 */
@Service("IPService")
@Transactional
public class IPImpl extends uploadBase implements IPService {

	private static final String PATTERNMAC = "^[A-F0-9]{2}(:[A-F0-9]{2}){5}$";

	private Logger logger = Logger.getLogger(IPImpl.class);

	@Resource
	private IPDao ipDao;
	@Resource
	private ModelDao modelDao;
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public Map<String, Object> IPListByInstallDetail(String ip_search,int currentPage, int rows,String ipstatus) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("ip_status", ipstatus);
		map.put("ip_search", ip_search);
		PageHelper.startPage(currentPage, rows);
		List<IP> list = ipDao.IPListByInstallDetail(map);
		PageInfo page = new PageInfo(list);
		long tottle = page.getTotal();
//		List<Map<String, Object>> reList = new ArrayList<Map<String, Object>>();
		map.put("totalCount", tottle);
		map.put("IPList", list);
		map.put("currentPage", currentPage);
		return map;
	}
	
	/**
	 * 查询某页所有的ip对象
	 * 
	 * @param currentPage
	 *            当前页码
	 * @param rows
	 *            每页行数
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public Map<String, Object> IPList(String ip_search,int currentPage, int rows) {
		PageHelper.startPage(currentPage, rows);
		
		List<IP> list = ipDao.IPList(ip_search);
		PageInfo page = new PageInfo(list);
		long tottle = page.getTotal();
//		int tottle = 100;
		List<Map<String, Object>> reList = new ArrayList<Map<String, Object>>();
		Map<String, Object> map1 = null;
		if(list !=null && !list.isEmpty()){
			for(IP ip :list ){
				map1 = beanToMap(ip);
				reList.add(map1);
			}
		}
		
		Map<String, Object> map = new HashMap<String, Object>();
//		System.out.println("总共" + tottle + "行,显示" + list.size() + "行");
		map.put("totalCount", tottle);
		map.put("IPList", reList);
		map.put("currentPage", currentPage);
		return map;
	}

	
	
	
	/**
	 * 根据反射机制获取对象的所有属性的值并封装成map
	 * @param obj
	 * @return
	 */
	 @SuppressWarnings("rawtypes")
	private static Map<String, Object> beanToMap(Object obj) { 
         Map<String, Object> params = new HashMap<String, Object>(0); 
         try { 
             PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean(); 
             PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(obj); 
             for (int i = 0; i < descriptors.length; i++) { 
                 String name = descriptors[i].getName(); 
                 if (!"class".equals(name)) { 
                	 Class type = descriptors[i].getPropertyType();
                	 String value = "";
                	 if(type.equals(Date.class)){
                		 Date date  = (Date) propertyUtilsBean.getNestedProperty(obj, name);
//                		 SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:MM:ss");
                		 SimpleDateFormat df=new SimpleDateFormat("yyyy/MM/dd");
                		 value=df.format(date);
                	 }else{
                		 value = String.valueOf(propertyUtilsBean.getNestedProperty(obj, name));
                	 }
                     params.put(name, value); 
                 } 
             } 
         } catch (Exception e) { 
             e.printStackTrace(); 
         } 
         return params; 
 }
		/**
		 * 新增一个ip对象
		 * 
		 * @param map
		 *            要新增的ip元素信息
		 * @return 结果信息
		 */
		@Override
		public Map<String, Object> insertIP(Map<String, String> map,
				RequestContext requestContext) {
			Map<String, Object> returnMap = new HashMap<String, Object>();

			String ipAddress = map.get("ipAddress");
			String mask = map.get("mask");

			List<Server> list = modelDao.getAllServer();// 获取所有的cobbler 服务器

			IpAddressUtil ipAddressUtil = null;
			ipAddressUtil = new IpAddressUtil(ipAddress, mask);
			String addSubnet = ipAddressUtil.getNetip();
			String tempSubNet = null;
			String batch = map.get("batChid");
			String mac = map.get("mac");
			String user = map.get("user");
			IP ip = new IP(mac, ipAddress, mask, batch, user);
			ip.setCreateTime(new Date());
			ip.setIpStatus("1");
			if (list != null && !list.isEmpty()) {
				for (Server server : list) {
					String serverIp = server.getIp();
					ipAddressUtil = new IpAddressUtil(serverIp, mask);
					tempSubNet = ipAddressUtil.getNetip();
					if (addSubnet.equals(tempSubNet)) {
						Integer serverId = server.getCsaId();
						// 找到了镜像库，可以新增
						ip.setMirrorLibraryId(serverId);
					}
				}
			}

			this.ipDao.insertIP(ip);
			returnMap.put("result", true);
			return returnMap;
		}

	/**
	 * 如果此删除前的ip已经装机，则修改以后可能会产生多个mac绑定一个Ip的情况或者一个多个ip绑定一个mac上，此处没有控制此情况
	 * 
	 * @param map
	 *            待修改的参数
	 * @return 修改状态
	 */
	@Override
	public Map<String, Object> updateIP(Map<String, String> map,
			RequestContext requestContext) {
		String ipAddress = map.get("ipAddress");
		String userIp = map.get("userIp");
		String mask = map.get("mask");
		String user = map.get("user");
		String batch = map.get("batChid");
		String mac = map.get("mac");
		String note = map.get("note");
		String id = map.get("id");

		IP ip = ipDao.findById(Integer.parseInt(id));
		ip.setMac(mac);
		ip.setMask(mask);
		ip.setIpAddress(ipAddress);
		ip.setBatChid(batch);

		Map<String, Object> returnMap = new HashMap<String, Object>();

		List<Server> list = modelDao.getAllServer();// 获取所有的cobbler 服务器

		IpAddressUtil ipAddressUtil = null;
		ipAddressUtil = new IpAddressUtil(ipAddress, mask);
		String addSubnet = ipAddressUtil.getNetip();
		String tempSubNet = null;
		if (list != null && !list.isEmpty()) {
			boolean isExist = false;
			for (Server server : list) {
				String serverIp = server.getIp();
				ipAddressUtil = new IpAddressUtil(serverIp, mask);
				tempSubNet = ipAddressUtil.getNetip();
				if (addSubnet.equals(tempSubNet)) {
					Integer serverId = server.getCsaId();
					ip.setMirrorLibraryId(serverId);
					isExist = true;
					break;
				}
			}
			if (!isExist)
				ip.setMirrorLibraryId(null);
		} else {
			ip.setMirrorLibraryId(null);
		}
		this.ipDao.updateIP(ip);
		IPLog ipLog = instanceIpLogs(ip.getCsaId(), note, user, userIp);
		ipDao.insertLog(ipLog);
		returnMap.put("result", true);
		return returnMap;
	}

	private IPLog instanceIpLogs(int ipCsaId,String notes,String userAccount,String userIp){
		IPLog ipLog = new IPLog( userAccount, new Date(), userIp, notes, ipCsaId);
		return ipLog;
	}

	/**
	 * 如果此删除前的ip已经装机，则删除了以后在下一次新增时可能 会产生多个mac绑定一个Ip的情况，此处没有控制此情况
	 * 
	 * @param map
	 *            要删除的map
	 * 
	 * @return 删除状态
	 */
	@Override
	public Map<String, Object> batchDeleteIps(Map<String, String> map) {
		Map<String, Object> returnMap = new HashMap<String, Object>();
		String[] ids = map.get("ids").split(",");
		Integer[] ia = new Integer[ids.length];
		for (int i = 0; i < ids.length; i++) {
			ia[i] = Integer.parseInt(ids[i]);
		}
		
		ipDao.batchDeleteIps(Arrays.asList(ia));
		ipDao.batchDeleteIpLogs(Arrays.asList(ia));
		returnMap.put("result", true);
		return returnMap;
	}

	/**
	 * 批量导入Ip对象，此处存在当已经装机时，或新增的ip没有找到同一 网段的镜像库，则判断为错误，不允许新增或修改。否则Ip存在则修
	 * 改，ip不存在则新增
	 * 
	 * @param request
	 *            request请求
	 * @param session
	 *            缓存
	 * 
	 * @return 处理状态信息
	 */
	@Override
	public Map<String, Object> inserIPs(String userIp,MultipartFile file,HttpSession session,RequestContext requestContext) {
		File f = null;
		String user = (String) session.getAttribute("userName");
		Map<String, Object> map = new HashMap<String, Object>();
		List<String> errorList = new ArrayList<String>();
		String fileName = file.getOriginalFilename().substring(
				file.getOriginalFilename().lastIndexOf("."));
		
		try{
			f = new File(file.getOriginalFilename());
			file.transferTo(f);
			System.out.println(f.getName());
		}catch(Exception e){
			e.printStackTrace();
		}
		
		
		InputStream is = null;
		XSSFWorkbook wbs = null;
		POIFSFileSystem poiin = null;
		try {
			is = new FileInputStream(f);
		} catch (FileNotFoundException e) {
			String patt = requestContext.getMessage("iperror3");
			logger.error(patt);
			map.put("tottle", 0);
			map.put("insert", 0);
			map.put("update", 0);
			map.put("error", 0);
			map.put("errorList", errorList);
			map.put("errMsg", patt);
			return map;
		}
		
		try {
			if (fileName.equals(".xlsx")) {
				wbs = new XSSFWorkbook(is);
				map = readXlsxFile(wbs, user,userIp,requestContext);
			} else if (fileName.equals(".xls") || fileName.equals(".et")) {
				poiin = new POIFSFileSystem(is);
				map = readXlsFile(poiin, user,userIp,requestContext);
			}
		} catch (Exception e) {
			String patt = requestContext.getMessage("iperror4");
			logger.error(patt);
			map.put("tottle", 0);
			map.put("insert", 0);
			map.put("update", 0);
			map.put("error", 0);
			map.put("errorList", errorList);
			map.put("errMsg", patt);
			return map;
		}

		return map;
	}
	
	/**
	 * 读取xlsx类型的excel文件
	 * 
	 * @param XSSFWorkbook
	 *            XSSFWorkbook
	 * @param user
	 *            当前用户
	 * @return 处理结果
	 */
	private Map<String, Object> readXlsxFile(XSSFWorkbook wbs, String user,
			String userIp, RequestContext requestContext) {
		Map<String, Object> map = new HashMap<String, Object>();
		List<IP> updateList = new ArrayList<IP>();
		List<IPLog> updateLogList = new ArrayList<IPLog>();
		List<IP> insertList = new ArrayList<IP>();
		List<String> errorList = new ArrayList<String>();

		XSSFSheet hssfSheet = null;
		XSSFRow datarow = null;
		XSSFCell cser = null;

		int max = 0;
		int min = 0;

		hssfSheet = wbs.getSheetAt(0);

		min = hssfSheet.getFirstRowNum();
		max = hssfSheet.getLastRowNum();

		if (max == min) {
			// 为空，没有数据
			String msg1 = requestContext.getMessage("iperror7");
			logger.warn(msg1);
			map.put("tottle", 0);
			map.put("insert", 0);
			map.put("update", 0);
			map.put("error", 0);
			map.put("errorList", errorList);
			map.put("errMsg", msg1);
			return map;
		}

		List<IP> ipList = ipDao.IPList("");
		Map<String, IP> tempMap = new HashMap<String, IP>();
		if (ipList != null && !ipList.isEmpty()) {
			for (IP ip : ipList) {
				String ipAddress = ip.getIpAddress();
				tempMap.put(ipAddress, ip);
			}
		}

		for (int i = 1; i < max + 1; i++) {
			datarow = hssfSheet.getRow(i);
//			cser = datarow.getCell(0);
			// int id = (int) cser.getNumericCellValue();

			cser = datarow.getCell(0);
			String ip = cser.getStringCellValue();

			cser = datarow.getCell(1);
			String mask = cser.getStringCellValue();

			cser = datarow.getCell(2);
			String mac = cser.getStringCellValue();

			cser = datarow.getCell(3);
			String batch = null;
			int cellType = cser.getCellType();
			if (1 == cellType) {
				// String
				batch = cser.getStringCellValue();
			} else {
				batch = String.valueOf(cser.getNumericCellValue());
			}

			boolean isValiIp = IpAddressUtil.isRegularIP(ip, 2);
			boolean isValiMask = IpAddressUtil.isRegularMask(mask);

			if (!isValiIp || !isValiMask
					|| !Pattern.compile(PATTERNMAC).matcher(mac).find()) {
				errorList.add(ip);
			} else {
				IP ipInf = null;
				// 找到了和此Ip ,mask想对应的镜像库网段
				if (tempMap.containsKey(ip)) {
					if (tempMap.get(ip).getIpStatus().equals("1")) {
						// 此ip没有装机，可以修改
						ipInf = tempMap.get(ip);
						ipInf.setCreateTime(new Date());
						ipInf.setBatChid(batch);
						ipInf.setMask(mask);
						ipInf.setMac(mac);
						Integer serviceId = getMirrorId(ip, mask);
						ipInf.setMirrorLibraryId((0 == serviceId) ? null
								: serviceId);
						IPLog ipLog = instanceIpLogs(ipInf.getCsaId(),
								"批量导入时修改！", user, userIp);
						updateLogList.add(ipLog);
						updateList.add(ipInf);
					} else {
						// 已安装过的ip不允许修改，跳过
						errorList.add(ip);
					}
				} else {
					ipInf = new IP();
					ipInf.setBatChid(batch);
					ipInf.setIpAddress(ip);
					ipInf.setCreateTime(new Date());
					ipInf.setIpStatus("1");
					ipInf.setMask(mask);
					ipInf.setMac(mac);
					ipInf.setUserAccount(user);
					Integer serviceId = getMirrorId(ip, mask);
					ipInf.setMirrorLibraryId((0 == serviceId) ? null
							: serviceId);
					insertList.add(ipInf);
				}

			}
		}

		int count = max - min;
		if (insertList.size() > 0) {
			// 由于是批量删除此处返回的修改数量不对，因此不以此作为判断标准
			ipDao.insertIps(insertList);
		}
		if (updateList.size() > 0) {
			// 由于是批量修改此处返回的修改数量不对，因此不以此作为判断标准
			ipDao.batchUpdateIps(updateList);
			ipDao.insertLogs(updateLogList);
		}
		String msg1 = requestContext.getMessage("iperror6");
		int error = count - insertList.size() - updateList.size();
		map.put("tottle", count);
		map.put("insert", insertList.size());
		map.put("update", updateList.size());
		map.put("error", error);
		map.put("errorList", errorList);
		map.put("errMsg", (error > 0) ? msg1 : "");
		return map;
	}

	/**
	 * 根据要编辑的ip和mask获取cobbler镜像库的id , id 为0，表示没有找到obbler镜像库，否则返回镜像库id
	 * 
	 * @param ip
	 *            要编辑的ip
	 * @param mask
	 *            要编辑的mask掩码
	 * @return 镜像库的id
	 */
	private Integer getMirrorId(String ip, String mask) {
		Integer serviceId = 0;
		IpAddressUtil ipAddressUtil = null;

		ipAddressUtil = new IpAddressUtil(ip, mask);
		String netIp = ipAddressUtil.getNetip();
		String serverNetIp = null;

		List<Server> list = modelDao.getAllServer();// 获取所有的cobbler 服务器

		Map<String, Server> tempServer = new HashMap<String, Server>();
		if (list != null && !list.isEmpty()) {
			for (Server server : list) {
				tempServer.put(server.getIp(), server);
			}
		}
		Iterator<String> iterator = tempServer.keySet().iterator();
		while (iterator.hasNext()) {
			String serverIp = iterator.next();
			ipAddressUtil = new IpAddressUtil(serverIp, mask);
			serverNetIp = ipAddressUtil.getNetip();

			// 没有找到和此Ip ,mask想对应的镜像库网段
			if (!serverNetIp.equals(netIp))
				continue;
			serviceId = tempServer.get(serverIp).getCsaId();
		}
		return serviceId;
	}

	/**
	 * 读取xls 或et格式的excel文件
	 * 
	 * @param poiin
	 *            POIFSFileSystem 流
	 * @param user
	 *            当前用户
	 * @return 返回的处理结果
	 */
	private Map<String, Object> readXlsFile(POIFSFileSystem poiin, String user,
			String userIp, RequestContext requestContext) {
		Map<String, Object> map = new HashMap<String, Object>();
		List<IP> updateList = new ArrayList<IP>();
		List<IPLog> updateLogList = new ArrayList<IPLog>();
		List<IP> insertList = new ArrayList<IP>();
		List<String> errorList = new ArrayList<String>();

		HSSFWorkbook wb = null;
		HSSFSheet hssfSheet = null;
		HSSFCell cser = null;
		HSSFRow datarow = null;
		int min = 0;
		int max = 0;

		try {
			wb = new HSSFWorkbook(poiin);
		} catch (IOException e) {
			String msg1 = requestContext.getMessage("iperror8");
			logger.error(msg1);
			map.put("tottle", 0);
			map.put("insert", 0);
			map.put("update", 0);
			map.put("error", 0);
			map.put("errorList", errorList);
			map.put("errMsg", msg1);
			return map;
		}
		hssfSheet = wb.getSheetAt(0);

		min = hssfSheet.getFirstRowNum();
		max = hssfSheet.getLastRowNum();
		if (max == min) {
			// 为空，没有数据
			String msg1 = requestContext.getMessage("iperror7");
			logger.warn(msg1);
			map.put("tottle", 0);
			map.put("insert", 0);
			map.put("update", 0);
			map.put("error", 0);
			map.put("errorList", errorList);
			map.put("errMsg", msg1);
			return map;
		}

		List<IP> ipList = ipDao.IPList("");
		Map<String, IP> tempMap = new HashMap<String, IP>();
		if (ipList != null && !ipList.isEmpty()) {
			for (IP ip : ipList) {
				String ipAddress = ip.getIpAddress();
				tempMap.put(ipAddress, ip);
			}
		}

		List<Server> list = modelDao.getAllServer();// 获取所有的cobbler 服务器

		Map<String, Server> tempServer = new HashMap<String, Server>();
		for (Server server : list) {
			tempServer.put(server.getIp(), server);
		}

		for (int i = 1; i < max + 1; i++) {
			datarow = hssfSheet.getRow(i);
//			cser = datarow.getCell(0);
			// int id = (int) cser.getNumericCellValue();

			cser = datarow.getCell(0);
			String ip = cser.getStringCellValue();

			cser = datarow.getCell(1);
			String mask = cser.getStringCellValue();

			cser = datarow.getCell(2);
			String mac = cser.getStringCellValue();

			cser = datarow.getCell(3);
			String batch = null;
			int cellType = cser.getCellType();
			if (1 == cellType) {
				// String
				batch = cser.getStringCellValue();
			} else {
				batch = String.valueOf(cser.getNumericCellValue());
			}

			boolean isValiIp = IpAddressUtil.isRegularIP(ip, 2);
			boolean isValiMask = IpAddressUtil.isRegularMask(mask);

			if (!isValiIp || !isValiMask
					|| !Pattern.compile(PATTERNMAC).matcher(mac).find()) {
				errorList.add(ip);
			} else {
				IP ipInf = null;
				// 找到了和此Ip ,则修改此ip
				if (tempMap.containsKey(ip)) {
					if (tempMap.get(ip).getIpStatus().equals("1")) {
						// 此ip没有装机，可以修改
						ipInf = tempMap.get(ip);
						ipInf.setCreateTime(new Date());
						ipInf.setBatChid(batch);
						ipInf.setMask(mask);
						ipInf.setMac(mac);
						Integer serviceId = getMirrorId(ip, mask);
						ipInf.setMirrorLibraryId((0 == serviceId) ? null
								: serviceId);
						IPLog ipLog = instanceIpLogs(ipInf.getCsaId(),
								"批量导入时修改！", user, userIp);
						updateLogList.add(ipLog);
						updateList.add(ipInf);
					} else {
						// 已安装过的ip不允许修改，跳过
						errorList.add(ip);
					}
				} else {
					ipInf = new IP();
					ipInf.setBatChid(batch);
					ipInf.setIpAddress(ip);
					ipInf.setCreateTime(new Date());
					ipInf.setIpStatus("1");
					ipInf.setMask(mask);
					ipInf.setMac(mac);
					ipInf.setUserAccount(user);
					Integer serviceId = getMirrorId(ip, mask);
					ipInf.setMirrorLibraryId((0 == serviceId) ? null
							: serviceId);
					insertList.add(ipInf);
				}

			}
		}

		int count = max - min;
		if (insertList.size() > 0) {
			// 由于是批量删除此处返回的修改数量不对，因此不以此作为判断标准
			ipDao.insertIps(insertList);
		}
		if (updateList.size() > 0) {
			// 由于是批量修改此处返回的修改数量不对，因此不以此作为判断标准
			ipDao.batchUpdateIps(updateList);
			ipDao.insertLogs(updateLogList);
		}
		String msg1 = requestContext.getMessage("iperror6");
		int error = count - insertList.size() - updateList.size();
		map.put("tottle", count);
		map.put("insert", insertList.size());
		map.put("update", updateList.size());
		map.put("error", error);
		map.put("errorList", errorList);
		map.put("errMsg", (error > 0) ? msg1 : "");
		return map;
	}
	

	@Override
	public List<IP> IPListByScheme(Integer csaid) {
		return ipDao.IPListByScheme(csaid);
	}

}
